
#include <GL/glx.h>
#include <GL/gl.h>
#include <unistd.h>
#include <assert.h>
#include <stdio.h>

static int attributeListSgl[] = {
    GLX_RGBA,
    GLX_RED_SIZE, 1,
    GLX_GREEN_SIZE, 1,
    GLX_BLUE_SIZE, 1,
    None};

static int attributeListDbl[] = {
    GLX_RGBA,
    GLX_RED_SIZE, 1,
    GLX_GREEN_SIZE, 1,
    GLX_BLUE_SIZE, 1,
    GLX_DOUBLEBUFFER,
    None};

static int  WaitForNotify(Display *d, XEvent *e, char *arg)
{
    return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
}

void SetOrthoProjection(unsigned short width, unsigned short height)
{
    float projection[16];

    projection[0] = 2.0f / width;
    projection[1] = 0.0f;
    projection[2] = 0.0f;
    projection[3] = 0.0f;

    projection[4] = 0.0f;
    projection[5] = 2.0f / -height;
    projection[6] = 0.0f;
    projection[7] = 0.0f;

    projection[8] = 0.0f;
    projection[9] = 0.0f;
    projection[10] = -2.0f / (100000 - 10);
    projection[11] = 0.0f;

    projection[12] = -1.0f;
    projection[13] = 1.0f;
    projection[14] = (100000 + 10) / (100000 - 10);
    projection[15] = 1.0f;

    glMatrixMode(GL_PROJECTION);
    glLoadMatrixf(projection);
}

void GetProjectionMatrix()
{
    GLdouble projection[16];
    glGetDoublev(GL_PROJECTION_MATRIX, projection);

    printf("projection matrix\n");
    for(int i = 0; i < 16; i++)
    {
        printf("proj[%d] = %f\n", i, projection[i]);
    }
}

void GetModelviewMatrix()
{
    GLdouble modelview[16];
    glGetDoublev(GL_MODELVIEW_MATRIX, modelview);

    printf("model matrix\n");
    for(int i = 0; i < 16; i++)
    {
        printf("model[%d] = %f\n", i, modelview[i]);
    }
}

void GetViewportMatrix()
{
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);

    printf("viewport matrix\n");
    for(int i = 0; i < 4; i++)
    {
        printf("viewport[%d] = %d\n", i, viewport[i]);
    }
}


int main(int argc, char **argv)
{
    Display *dpy;
    XVisualInfo *vi;
    Colormap cmap;
    XSetWindowAttributes swa;
    Window win;
    GLXContext cx;
    XEvent event;
    int swap_flag = false;
    Bool result = false;

    dpy = XOpenDisplay(0);

    //vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListSgl);
    vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListDbl);
    if(vi == NULL)
    {
        vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeListDbl);
        swap_flag = true;
    }

    cx = glXCreateContext(dpy, vi, 0, GL_TRUE);

    cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);

    fprintf(stderr, "vi->depth = %d\n", vi->depth);

    swa.colormap = cmap;
    swa.border_pixel = 0;
    //swa.event_mask = StructureNotifyMask;
    swa.event_mask = ExposureMask;
    win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 480, 320,
            0, vi->depth, InputOutput, vi->visual,
            CWBorderPixel | CWColormap | CWEventMask, &swa);
    XMapWindow(dpy, win);
    //XIfEvent(dpy, &event, WaitForNotify, (char*)win);

    result = glXMakeCurrent(dpy, win, cx);
    assert(result == true);

    glViewport(0, 0, 480, 320);
    SetOrthoProjection(480, 320);

    GetProjectionMatrix();
    GetViewportMatrix();
    GetModelviewMatrix();

    glClearColor(1, 1, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    glColor3d(1.0, 0.0, 0.0);
    glBegin(GL_POLYGON);
    glVertex2d(100.0, 50.0);
    glVertex2d(300.0, 50.0);
    glVertex2d(300.0, 150.0);
    glVertex2d(100.0, 150.0);
    glEnd();

    //glColor3d(1.0, 0.0, 0.0);
    //glBegin(GL_POLYGON);
    //glVertex2d(-0.9, -0.9);
    //glVertex2d(0.9, -0.9);
    //glVertex2d(0.9, 0.9);
    //glVertex2d(-0.9, 0.9);
    //glEnd();

    glFlush();

    glXSwapBuffers(dpy, win);

    glXSwapBuffers(dpy, win);

    if(swap_flag)
    {
        glXSwapBuffers(dpy, win);
    }

    sleep(10);
}

